package com.example.demo2;

import android.content.Context;
import android.location.Location;
import android.os.Looper;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.work.Worker;
import androidx.work.WorkerParameters;

import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.tasks.OnSuccessListener;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;

import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class LocationUploadWorker extends Worker {

    private static final String TAG = "LocationUploadWorker";
    private FusedLocationProviderClient fusedLocationClient;
    private String deviceId;

    public LocationUploadWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(context);
        deviceId = android.provider.Settings.Secure.getString(context.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
    }

    @NonNull
    @Override
    public Result doWork() {
        LocationRequest locationRequest = LocationRequest.create();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(10000); // 10 seconds
        locationRequest.setFastestInterval(5000); // 5 seconds

        try {
            fusedLocationClient.getLastLocation().addOnSuccessListener(new OnSuccessListener<Location>() {
                @Override
                public void onSuccess(Location location) {
                    if (location != null) {
                        double[] bd09Coords = wgs84ToBd09(location.getLatitude(), location.getLongitude());
                        String latitude = String.valueOf(bd09Coords[0]);
                        String longitude = String.valueOf(bd09Coords[1]);
                        sendPostRequest(deviceId, latitude, longitude);
                    }
                }
            });
        } catch (SecurityException e) {
            Log.e(TAG, "Location permission not granted", e);
            return Result.failure();
        }

        return Result.success();
    }

    private void sendPostRequest(String deviceId, String latitude, String longitude) {
        OkHttpClient client = new OkHttpClient();

        // 构建 JSON 请求体
        JSONObject jsonBody = new JSONObject();
        try {
            jsonBody.put("deviceId", deviceId);
            jsonBody.put("latitude", latitude);
            jsonBody.put("longitude", longitude);
        } catch (JSONException e) {
            e.printStackTrace();
            Log.e(TAG, "Failed to build JSON request body: " + e.getMessage());
            return;
        }

        RequestBody body = RequestBody.create(jsonBody.toString(), MediaType.parse("application/json"));

        Request request = new Request.Builder()
                .url("http://47.92.209.179:9090/location/saveDeviceLocation")
                .post(body)
                .addHeader("Content-Type", "application/json")
                .build();

        try {
            Response response = client.newCall(request).execute();
            int statusCode = response.code();
            String result = null;
            if (response.isSuccessful()) {
                result = response.body().string();
                Log.d(TAG, "POST request successful (Status Code: " + statusCode + "): " + result);
            } else {
                result = response.body() != null ? response.body().string() : "No response body";
                Log.e(TAG, "POST request failed (Status Code: " + statusCode + "): " + result);
            }
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(TAG, "POST request error: " + e.getMessage());
        }
    }

    // WGS - 84 转 BD - 09 坐标转换方法
    private double[] wgs84ToBd09(double wgLat, double wgLon) {
        double[] gcj02 = wgs84ToGcj02(wgLat, wgLon);
        return gcj02ToBd09(gcj02[0], gcj02[1]);
    }

    // WGS - 84 转 GCJ - 02 坐标转换方法
    private double[] wgs84ToGcj02(double wgLat, double wgLon) {
        if (outOfChina(wgLat, wgLon)) {
            return new double[]{wgLat, wgLon};
        }
        double dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
        double dLon = transformLon(wgLon - 105.0, wgLat - 35.0);
        double radLat = wgLat / 180.0 * Math.PI;
        double magic = Math.sin(radLat);
        magic = 1 - 0.00669342162296594323 * magic * magic;
        double sqrtMagic = Math.sqrt(magic);
        dLat = (dLat * 180.0) / ((6378245.0 * (1 - 0.00669342162296594323)) / (magic * sqrtMagic) * Math.PI);
        dLon = (dLon * 180.0) / (6378245.0 / sqrtMagic * Math.cos(radLat) * Math.PI);
        double mgLat = wgLat + dLat;
        double mgLon = wgLon + dLon;
        return new double[]{mgLat, mgLon};
    }

    // GCJ - 02 转 BD - 09 坐标转换方法
    private double[] gcj02ToBd09(double ggLat, double ggLon) {
        double x = ggLon, y = ggLat;
        double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * Math.PI);
        double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * Math.PI);
        double bdLon = z * Math.cos(theta) + 0.0065;
        double bdLat = z * Math.sin(theta) + 0.006;
        return new double[]{bdLat, bdLon};
    }

    // 判断是否在中国境内
    private boolean outOfChina(double lat, double lon) {
        return (lon < 72.004 || lon > 137.8347) || (lat < 0.8293 || lat > 55.8271);
    }

    // 纬度转换辅助方法
    private double transformLat(double x, double y) {
        double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin(y / 3.0 * Math.PI)) * 2.0 / 3.0;
        ret += (160.0 * Math.sin(y / 12.0 * Math.PI) + 320 * Math.sin(y * Math.PI / 30.0)) * 2.0 / 3.0;
        return ret;
    }

    // 经度转换辅助方法
    private double transformLon(double x, double y) {
        double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
        ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0;
        ret += (20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin(x / 3.0 * Math.PI)) * 2.0 / 3.0;
        ret += (150.0 * Math.sin(x / 12.0 * Math.PI) + 300.0 * Math.sin(x / 30.0 * Math.PI)) * 2.0 / 3.0;
        return ret;
    }
}